package com.shuwen.gcdj.service.statistic;
/**
 * @author Yangx
 */

import com.alibaba.excel.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shuwen.gcdj.bean.conditionMonitoring.request.HealthQueryReq;
import com.shuwen.gcdj.bean.conditionMonitoring.request.HealthReq;
import com.shuwen.gcdj.bean.conditionMonitoring.request.StatisticsHealthSingleQueryReq;
import com.shuwen.gcdj.bean.conditionMonitoring.response.*;
import com.shuwen.gcdj.common.api.CommonResult;
import com.shuwen.gcdj.common.constant.Constants;
import com.shuwen.gcdj.entity.basics.BasicsEquipment;
import com.shuwen.gcdj.entity.statistics.StatisticsHealth;
import com.shuwen.gcdj.mapper.mysql.Statistic.StatisticsHealthMapper;
import com.shuwen.gcdj.mapper.mysql.Statistic.StatisticsOperatingModeLoadMapper;
import com.shuwen.gcdj.mapper.mysql.basics.BasicsEquipmentMapper;
import com.shuwen.gcdj.service.BaseService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@AllArgsConstructor
@Slf4j
public class StatisticsHealthService extends BaseService<StatisticsHealthMapper, StatisticsHealth> {

    private final StatisticsHealthMapper statisticsHealthMapper;
    private final BasicsEquipmentMapper basicsEquipmentMapper;
    private final StatisticsOperatingModeLoadMapper statisticsOperatingModeLoadMapper;

    public CommonResult<StatisticsHealthResp> getStatisticsOperatingmodeload(StatisticsHealthSingleQueryReq req) {
        StatisticsHealthResp statisticsHealthResp = new StatisticsHealthResp();
        //查询健康度载荷图谱
        StatisticsOperatingmodeloadResp statisticsOperatingmodeloadResp = statisticsOperatingModeLoadMapper.GetFist(req);
        if (statisticsOperatingmodeloadResp == null) {
            return CommonResult.success(statisticsHealthResp);
        }
        String loadData = statisticsOperatingmodeloadResp.getLoad();
        if (loadData == null || loadData.isEmpty()) {
            return CommonResult.success(statisticsHealthResp);
        }
        List<String> loads = solveUrl(loadData);
        //对载荷图谱数据进行处理与排序
        List<LoadByOrderResp> loadByOrderRespList = new ArrayList<>();
        for (String load : loads) {
            String[] ary = load.split(",");
            LoadByOrderResp loadByOrderResp = new LoadByOrderResp();
            loadByOrderResp.setIndex(Double.valueOf(ary[0]));
            loadByOrderResp.setValue(Double.valueOf(ary[1]));
            loadByOrderRespList.add(loadByOrderResp);
        }
        loadByOrderRespList = loadByOrderRespList.stream().sorted(Comparator.comparing(LoadByOrderResp::getIndex)).collect(Collectors.toList());
        statisticsHealthResp.setDateValue(loadByOrderRespList.stream().map(temp -> temp.getIndex().toString()).collect(Collectors.toList()));
        statisticsHealthResp.setHealthValue(loadByOrderRespList.stream().map(LoadByOrderResp::getValue).collect(Collectors.toList()));
        return CommonResult.success(statisticsHealthResp);
    }

    //取出String中()中的字段
    public List<String> solveUrl(String url) {   // 处理函数
        String pattern = "\\([^)]*\\)"; // 匹配（） 的表达式
        List<String> data = new ArrayList<>();
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(url);
        while (m.find()) {    // 当字符串中有匹配到 {} 时
            String param = m.group(0);  // {} 和里面的内容
            String a = param.substring(1, param.length() - 1);
            data.add(a);
        }
        return data;
    }

    public CommonResult<List<HealthyStatisticsRateResp>> getToDayCompleteMachineHealth(StatisticsHealthSingleQueryReq req) {
        List<HealthyStatisticsRateResp> resp = new ArrayList<>();
        LocalDate date = LocalDate.now();
        Integer startYear = date.plusMonths(-12).getYear();
        Integer endYear = date.getYear();
        HealthQueryReq healthQueryReq = new HealthQueryReq();
        healthQueryReq.setEndYear(endYear);
        healthQueryReq.setStartYear(startYear);
        healthQueryReq.setEquipmentCode(req.getEquipmentCode());
        //易耗损区域展示携带轴承健康度
        if(req.getLocation().equals(Constants.HEALTH_CONSUMABLE_VALUE))
        {
            List<Integer> list = Stream.of(Constants.HEALTH_CONSUMABLE_VALUE,Constants.HEALTH_BEARINGS_VALUE).collect(Collectors.toList());
            healthQueryReq.setLocationList(list);
        }else {
            healthQueryReq.setLocation(req.getLocation());
        }
        List<HealthResp> healths = statisticsHealthMapper.getList(healthQueryReq);
        if (CollectionUtils.isEmpty(healths)) {
            return CommonResult.success(resp);
        }
        List<String> names = healths.stream().map(HealthResp::getEvaluateObject).distinct().collect(Collectors.toList());
        for (String name : names) {
            HealthyStatisticsRateResp healthyStatisticsRateResp = new HealthyStatisticsRateResp();
            HealthResp healthResp = healths.stream().filter(health->health.evaluateObject.equals(name)).findFirst().orElse(null);
            Float value = (float) 0;
            if (healthResp != null) {
                value = healthResp.getStatusValue();
            }
            //卷筒当前健康度趋势
            switch (req.getLocation()){
                case 2:
                    //卷筒当前健康度趋势
                    StatisticsHealthSingleQueryReq healthQueryReq1 = new StatisticsHealthSingleQueryReq();
                    healthQueryReq1.setLocation(Constants.HEALTH_RELL_VALUE);
                    healthQueryReq1.setEquipmentCode(req.getEquipmentCode());
                    healthQueryReq1.setEvaluateObject(name);
                    StatisticsHealthResp statisticsHealthResp = getStatisticsOperatingmodeload(healthQueryReq1).getData();
                    healthyStatisticsRateResp.setStatusValue(value.intValue());
                    healthyStatisticsRateResp.setName(name);
                    healthyStatisticsRateResp.setHealthValue(statisticsHealthResp.getHealthValue());
                    healthyStatisticsRateResp.setDateValue(statisticsHealthResp.getDateValue());
                    resp.add(healthyStatisticsRateResp);
                    break;
                case 3:
                    //零部件当前健康度趋势
                    healthyStatisticsRateResp.setStatusValue(value.intValue());
                    healthyStatisticsRateResp.setName(name);
                    resp.add(healthyStatisticsRateResp);
                    if (resp.size() >= 5)
                        return CommonResult.success(resp);
                    break;
                default:
                    break;
            }
        }
        resp = resp.stream().sorted(Comparator.comparing(HealthyStatisticsRateResp::getName)).collect(Collectors.toList());
        return CommonResult.success(resp);
    }

    public CommonResult<HealthyStatisticsRateResp> getToDayMachineHealth(StatisticsHealthSingleQueryReq req) {
        HealthyStatisticsRateResp resp = new HealthyStatisticsRateResp();
        HealthQueryReq healthQueryReq = new HealthQueryReq();
        healthQueryReq.setLocation(req.getLocation());
        healthQueryReq.setEquipmentCode(req.getEquipmentCode());
        healthQueryReq.setEvaluateObject(Constants.COMPLETE_MACHINE);
        HealthResp healthResp = statisticsHealthMapper.getSnigle(healthQueryReq);
        if (healthResp == null) {
            return CommonResult.success(resp);
        }
        resp.setName(healthResp.getEvaluateObject());
        resp.setStatusValue(healthResp.getStatusValue().intValue());
        return CommonResult.success(resp);
    }

    public CommonResult<List<StatisticsHealthResp>> getHistoryByHealth(HealthReq req) {
        String[] colors = {"#4BA6DD", "#00428E", "#FFC53F", "#A0D911", "#C5D8FF", "#98FB98", "#4682B4", "#FFEFD5", "#FFFF00", "#FFA500"};
        List<StatisticsHealthResp> resp = new ArrayList<>();
        StatisticsHealthResp statisticsHealthResp;
        LocalDate date = LocalDate.now();
        List<String> dateValue = new ArrayList<>();
        List<Double> healthValue = new ArrayList<>();
        HealthQueryReq healthQueryReq = new HealthQueryReq();
        healthQueryReq.setLocation(req.getLocation());
        healthQueryReq.setEquipmentCode(req.getEquipmentCode());
        healthQueryReq.setStatisticsType(req.getStatisticsType());
        int j = 0;
        switch (req.getStatisticsType()) {
            case 1:
                //按月统计每月卷筒平均健康度平均历史趋势数据
                healthQueryReq.setStartYear(date.plusMonths(-12).getYear());
                healthQueryReq.setEndYear(date.getYear());
                List<Integer[]> yearMonths = new ArrayList<>();
                for (int i = 0; i < 12; i++) {
                    int year = date.plusMonths(-i).getYear();
                    int month = date.plusMonths(-i).getMonthValue();
                    Integer[] ints = {year, month};
                    yearMonths.add(ints);
                }
                List<HealthResp> healths = statisticsHealthMapper.getList(healthQueryReq);
                if (healths == null || CollectionUtils.isEmpty(healths)) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    for (Integer[] i : yearMonths) {
                        healthValue.add(0, 0.0);
                        dateValue.add(0, i[0] + "-" + i[1]);
                    }
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setHealthValue(healthValue);
                    resp.add(statisticsHealthResp);
                    return CommonResult.success(resp);
                }
                List<String> names = healths.stream().map(HealthResp::getEvaluateObject).distinct().collect(Collectors.toList());
                for (String name : names) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    healthValue = new ArrayList<>();
                    dateValue = new ArrayList<>();
                    for (Integer[] i : yearMonths) {
                        Double value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) && Objects.equals(t.getMonth(), i[1]) && Objects.equals(t.getEvaluateObject(), name))
                                .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        healthValue.add(0, value);
                        dateValue.add(0, i[0] + "-" + i[1]);
                    }
                    statisticsHealthResp.setName(name);
                    statisticsHealthResp.setHealthValue(healthValue);
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setColor(colors[j]);
                    j++;
                    resp.add(statisticsHealthResp);
                }
                break;
            case 3:
                //按天查询每天整机健康度平均历史趋势
                healthQueryReq.setStartYear(date.plusDays(-30).getYear());
                healthQueryReq.setEndYear(date.getYear());
                List<Integer[]> monthDays = new ArrayList<>();
                for (int i = 0; i < 30; i++) {
                    int year = date.plusDays(-i).getYear();
                    int month = date.plusDays(-i).getMonthValue();
                    int day = date.plusDays(-i).getDayOfMonth();
                    Integer[] ints = {year, month, day};
                    monthDays.add(ints);
                }
                healths = statisticsHealthMapper.getList(healthQueryReq);
                if (healths == null || CollectionUtils.isEmpty(healths)) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    for (Integer[] i : monthDays) {
                        healthValue.add(0, 0.0);
                        dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                    }
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setHealthValue(healthValue);
                    resp.add(statisticsHealthResp);
                    return CommonResult.success(resp);
                }
                names = healths.stream().map(HealthResp::getEvaluateObject).distinct().collect(Collectors.toList());
                for (String name : names) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    healthValue = new ArrayList<>();
                    dateValue = new ArrayList<>();
                    for (Integer[] i : monthDays) {
                        Double value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) &&
                                        Objects.equals(t.getMonth(), i[1]) && Objects.equals(t.getDay(), i[2]) &&
                                        Objects.equals(t.getEvaluateObject(), name))
                                .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        healthValue.add(0, value);
                        dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                    }
                    statisticsHealthResp.setName(name);
                    statisticsHealthResp.setHealthValue(healthValue);
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setColor(colors[j]);
                    j++;
                    resp.add(statisticsHealthResp);
                }
                break;
            case 2:
                //按季查询每15天整机健康度平均历史趋势
                healthQueryReq.setStartYear(date.plusMonths(-3).getYear());
                healthQueryReq.setEndYear(date.getYear());
                monthDays = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    int year = date.plusMonths(-i).getYear();
                    int month = date.plusMonths(-i).getMonthValue();
                    Integer[] ints = {year, month, 1};
                    Integer[] ints2 = {year, month, 15};
                    monthDays.add(ints2);
                    monthDays.add(ints);
                }
                healths = statisticsHealthMapper.getList(healthQueryReq);
                if (healths == null || CollectionUtils.isEmpty(healths)) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    for (Integer[] i : monthDays) {
                        healthValue.add(0, 0.0);
                        dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                    }
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setHealthValue(healthValue);
                    resp.add(statisticsHealthResp);
                    return CommonResult.success(resp);
                }
                names = healths.stream().map(HealthResp::getEvaluateObject).distinct().collect(Collectors.toList());
                for (String name : names) {
                    statisticsHealthResp = new StatisticsHealthResp();
                    healthValue = new ArrayList<>();
                    dateValue = new ArrayList<>();
                    for (Integer[] i : monthDays) {
                        double value;
                        int month;
                        int year;
                        if (i[2] == 1) {
                            if (i[1] - 1 == 0) {
                                month = 12;
                                year = i[0] - 1;
                            } else {
                                month = i[1] - 1;
                                year = i[0];
                            }
                            value = healths.stream().filter(t -> Objects.equals(t.getYear(), year) && Objects.equals(t.getMonth(), month) && t.getDay() > 15 && t.getDay() <= 31 && Objects.equals(t.getEvaluateObject(), name))
                                    .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        } else {
                            value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) && Objects.equals(t.getMonth(), i[1]) && t.getDay() >= 1 && t.getDay() <= 15 && Objects.equals(t.getEvaluateObject(), name))
                                    .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        }
                        healthValue.add(0, value);
                        dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                    }
                    statisticsHealthResp.setName(name);
                    statisticsHealthResp.setHealthValue(healthValue);
                    statisticsHealthResp.setDateValue(dateValue);
                    statisticsHealthResp.setColor(colors[j]);
                    j++;
                    resp.add(statisticsHealthResp);
                }
                break;
            default:
                break;
        }
        return CommonResult.success(resp);
    }


    public CommonResult<StatisticsHealthResp> getHistoryByCompleteMachineHealth(HealthQueryReq req) {
        StatisticsHealthResp resp = new StatisticsHealthResp();
        //整机位置
        req.setLocation(1);
        LocalDate date = LocalDate.now();
        List<String> dateValue = new ArrayList<>();
        List<Double> healthValue = new ArrayList<>();
        switch (req.getStatisticsType()) {
            case 1:
                //按月查询每月整机健康度平均值历史趋势
                req.setStartYear(date.plusMonths(-12).getYear());
                req.setEndYear(date.getYear());
                List<Integer[]> yearMonths = new ArrayList<>();
                for (int i = 0; i < 12; i++) {
                    int year = date.plusMonths(-i).getYear();
                    int month = date.plusMonths(-i).getMonthValue();
                    Integer[] ints = {year, month};
                    yearMonths.add(ints);
                }
                List<HealthResp> healths = statisticsHealthMapper.getList(req);
                if (CollectionUtils.isEmpty(healths))
                    return CommonResult.success(resp);
                for (Integer[] i : yearMonths) {
                    Double value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) && Objects.equals(t.getMonth(), i[1]))
                            .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                    healthValue.add(0, value);
                    dateValue.add(0, i[0] + "-" + i[1]);
                }
                resp.setDateValue(dateValue);
                resp.setHealthValue(healthValue);
                break;
            case 2:
                //按天查询每天整机健康度平均值历史趋势
                req.setStartYear(date.plusDays(-30).getYear());
                req.setEndYear(date.getYear());
                List<Integer[]> monthDays = new ArrayList<>();
                for (int i = 0; i < 30; i++) {
                    int year = date.minusDays(i).getYear();
                    int month = date.minusDays(i).getMonthValue();
                    int day = date.minusDays(i).getDayOfMonth();
                    Integer[] ints = {year, month, day};
                    monthDays.add(ints);
                }
                healths = statisticsHealthMapper.getList(req);
                if (CollectionUtils.isEmpty(healths))
                    return CommonResult.success(resp);
                for (Integer[] i : monthDays) {
                    Double value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) && Objects.equals(t.getMonth(), i[1]) && Objects.equals(t.getDay(), i[2]))
                            .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                    healthValue.add(0, value);
                    dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                }
                resp.setDateValue(dateValue);
                resp.setHealthValue(healthValue);
                break;
            case 3:
                //按季查询每15天的整机健康度平均值历史趋势
                req.setStartYear(date.plusMonths(-3).getYear());
                req.setEndYear(date.getYear());
                monthDays = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    int year = date.plusMonths(-i).getYear();
                    int month = date.plusMonths(-i).getMonthValue();
                    Integer[] ints = {year, month, 1};
                    Integer[] ints2 = {year, month, 15};
                    monthDays.add(ints2);
                    monthDays.add(ints);
                }
                healths = statisticsHealthMapper.getList(req);
                if (CollectionUtils.isEmpty(healths))
                    return CommonResult.success(resp);
                for (Integer[] i : monthDays) {
                    double value;
                    int month = 0;
                    int year = 0;
                    if (i[2] == 1) {
                        if (i[1] - 1 == 0) {
                            month = 12;
                            year = i[0] - 1;
                            int lastYear = year;
                            int finalMonth = month;
                            value = healths.stream().filter(t -> Objects.equals(t.getYear(), lastYear) && Objects.equals(t.getMonth(), finalMonth) && t.getDay() > 15 && t.getDay() <= 31)
                                    .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        } else {
                            month = i[1] - 1;
                            year = i[0];
                            int finalYear = year;
                            int lastMonth = month;
                            value = healths.stream().filter(t -> Objects.equals(t.getYear(), finalYear) && Objects.equals(t.getMonth(), lastMonth) && t.getDay() > 15 && t.getDay() <= 31)
                                    .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                        }
                    } else {
                        value = healths.stream().filter(t -> Objects.equals(t.getYear(), i[0]) && Objects.equals(t.getMonth(), i[1]) && t.getDay() >= 1 && t.getDay() <= 15)
                                .mapToDouble(HealthResp::getStatusValue).average().orElse(0);
                    }
                    healthValue.add(0, value);
                    dateValue.add(0, i[0] + "-" + i[1] + "-" + i[2]);
                }
                resp.setDateValue(dateValue);
                resp.setHealthValue(healthValue);
                break;
            default:
                break;
        }
        return CommonResult.success(resp);
    }

    public CommonResult<List<EquipmentDictSettingResp>> getEquipmentCodeList(Integer area) {
        List<EquipmentDictSettingResp> resp = new ArrayList<>();
        List<BasicsEquipment> basicsEquipments = basicsEquipmentMapper.selectList(new QueryWrapper<BasicsEquipment>().lambda()
                .eq(BasicsEquipment::getIsDelete,Constants.IS_DELETE_NORMAL)
                .eq(BasicsEquipment::getAreaLocation, area));
        if (CollectionUtils.isEmpty(basicsEquipments))
            return CommonResult.success(resp);
        for (BasicsEquipment item : basicsEquipments) {
            EquipmentDictSettingResp dictSettingResp = new EquipmentDictSettingResp();
            dictSettingResp.setName(item.getCode());
            dictSettingResp.setValue(item.getCode());
            resp.add(dictSettingResp);
        }
        return CommonResult.success(resp.stream().sorted(Comparator.comparing(EquipmentDictSettingResp::getValue)).collect(Collectors.toList()));
    }

    public CommonResult<List<EquipmentDictSettingResp>> getEquipmentNameList(Integer area) {
        List<EquipmentDictSettingResp> resp = new ArrayList<>();
        List<BasicsEquipment> basicsEquipments = basicsEquipmentMapper.selectList(new QueryWrapper<BasicsEquipment>().lambda()
                .eq(BasicsEquipment::getIsDelete,Constants.IS_DELETE_NORMAL)
                .eq(BasicsEquipment::getAreaLocation, area));
        if (CollectionUtils.isEmpty(basicsEquipments))
            return CommonResult.success(resp);
        for (BasicsEquipment item : basicsEquipments) {
            EquipmentDictSettingResp dictSettingResp = new EquipmentDictSettingResp();
            dictSettingResp.setName(item.getName());
            dictSettingResp.setValue(item.getCode());
            resp.add(dictSettingResp);
        }
        return CommonResult.success(resp.stream().sorted(Comparator.comparing(EquipmentDictSettingResp::getValue)).collect(Collectors.toList()));
    }

}
